package com.heima.admin.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.admin.mapper.AdChannelMapper;
import com.heima.admin.mapper.AdSensitiveMapper;
import com.heima.admin.service.WemediaNewsAutoScanService;
import com.heima.aliyun.GreeTextScan;
import com.heima.aliyun.GreenImageScan;
import com.heima.common.exception.CustException;
import com.heima.feigns.article.ArticleFeign;
import com.heima.feigns.wemedia.WemediaFeign;
import com.heima.model.admin.pojos.AdChannel;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.utils.common.SensitiveWordUtil;
import com.sun.xml.bind.v2.TODO;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
@Slf4j
public class WemediaNewsAutoScanServiceImpl implements WemediaNewsAutoScanService {
    @Autowired
    WemediaFeign wemediaFeign;
    @Autowired
    ArticleFeign articleFeign;
    @Value("${file.oss.web-site}")
    private String website;
    @Autowired
    AdSensitiveMapper adSensitiveMapper;
    @Autowired
    AdChannelMapper adChannelMapper;
    @Autowired
    GreeTextScan greeTextScan;
    @Autowired
    GreenImageScan greenImageScan;
    /**
     * 自媒体文章审核
     *
     * @param wmNewsId
     */
    @Override
    @GlobalTransactional
    public void autoScanByMediaNewsId(Integer wmNewsId) {
        /*参数校验*/
        if (wmNewsId == null) {
            log.error("审核的ID为空");
            CustException.cust(AppHttpCodeEnum.PARAM_REQUIRE);
            return;
        }
        /*1根据ID查询自媒体文章信息*/
        WmNews wmNews = wemediaFeign.findById(wmNewsId);
        if (wmNews == null) {
            log.error("审核的文章不存在,自媒体ID：{}", wmNewsId);
            CustException.cust(AppHttpCodeEnum.PARAM_REQUIRE);
            return;
        }
        /*判断文章的状态*/
        /*2若文章状态为8，（审核通过待发布）,且发布时间小于等于当前时间，直接保存数据*/
        if (wmNews.getStatus().equals(WmNews.Status.SUCCESS.getCode())
                && wmNews.getPublishTime().getTime() <= System.currentTimeMillis()) {
            //保存数据
            saveAppArticle(wmNews);
            return;
        }
        /*3若文章状态wei4，（人工审核通过），直接保存数据和创建索引*/
        if (wmNews.getStatus().equals(WmNews.Status.ADMIN_SUCCESS.getCode())) {
            saveAppArticle(wmNews);
            return;
        }
        /*4若文章状态为1，（待审核）*/
        if (wmNews.getStatus().equals(WmNews.Status.SUBMIT.getCode())) {
            /*抽取文章图片和文本*/
            Map<String, Object> contentAndImageResult = handleTextAndImages(wmNews);
            /*调用阿里云文本反垃圾*/
            //4.1 自管理敏感词审核
            boolean isSensitveScan = handleSensitive((String) contentAndImageResult.get("content"), wmNews);
            if (!isSensitveScan) {
                return;
            }
            //4.2 阿里云审核文本内容
            boolean isTextScan = handleTextScan((String) contentAndImageResult.get("content"), wmNews);
            if (!isTextScan) {
                return;
            }
            //4.3 阿里云图片审核
            boolean isImageScan = handleImagesScan((List<String>) contentAndImageResult.get("image"), wmNews);
            if (!isImageScan) {
                return;
            }
            //4.4 如果发布时间 大于 当前时间， 修改wmNews 文章状态=8
            if (wmNews.getPublishTime().getTime() > System.currentTimeMillis()) {
                updateWmNews(wmNews, (short) 8, "文章审核通过，待发布");
                return;
            }
            //5 审核通过，保存文章相关信息（三张表）， 修改文章的状态=9 已发布
            saveAppArticle(wmNews);
            wmNews.setStatus((short)9);
            return;
        }
    }

    /**
     * 审核图片内容-阿里云
     *
     * @param /content
     * @param /wmNews
     * @return
     */
    private boolean handleImagesScan(List<String> images, WmNews wmNews) {
        if (images == null || images.size() == 0) {
            return true;
        }
        boolean flag = true;
        try {
            images.stream().distinct().collect(Collectors.toList());
            Map map = greenImageScan.imageUrlScan(images);
            /*审核不通过*/
            if (map.get("suggestion").equals("block")) {
                updateWmNews(wmNews,(short)2,"文章图片有违规");
                flag = false;
            }
            /*人工审核*/
            if (map.get("suggestion").equals("review")) {
                updateWmNews(wmNews, (short) 2, "文章图片有不确定元素");
                flag = false;
            }
        } catch (Exception e) {
            e.printStackTrace();
            updateWmNews(wmNews,(short)2,"阿里云审核失败，转入人工审核");
            flag = false;
        }
        return flag;
    }

    /**
     * 审核文本内容-阿里云
     *
     * @param /content
     * @param /wmNews
     * @return
     */

    private boolean handleTextScan(String content, WmNews wmNews) {
        boolean flag = true;
        try {
            Map map = greeTextScan.greeTextScan(content);
            if (map.get("suggestion").equals("block")) {
                flag = false;
                updateWmNews(wmNews,(short)2,"文本内容中有敏感词");
            }
            if (map.get("suggestion").equals("review")) {
                flag = false;
                updateWmNews(wmNews,(short)2,"文本内容需要人工审核");
            }
        } catch (Exception e) {
            e.printStackTrace();
            flag = false;
            log.error("阿里云文本审核失败，转入人工审核，e:{}", e);
            updateWmNews(wmNews,(short)3,"阿里云文本审核失败，转入人工审核");
        }
        return flag;
    }

    private Map<String,Object> handleTextAndImages(WmNews wmNews) {
        /*获取图文内容，并将其转换成一组map对象*/
        String content = wmNews.getContent();
        if (StringUtils.isBlank(content) || content.length() > 10000) {
            return null;
        }
        List<Map> mapList = JSON.parseArray(content, Map.class);
            /*文本内容*/
        String contents = mapList.stream().filter(x -> x.get("type").equals("text"))
                .map(y -> y.get("value").toString())
                .collect(Collectors.joining());
            /*图片内容*/
        List<String> images = mapList.stream().filter(x -> x.get("type").equals("image"))
                .map(y -> y.get("value").toString())
                .collect(Collectors.toList());


        /*2处理封面前缀*/
        String imagesCover = wmNews.getImages();
            /*添加到内容图片列表*/
        if (StringUtils.isNotBlank(imagesCover)) {
            images.addAll(
                    Stream.of(imagesCover.split(","))
                            .map(x -> website + x)
                            .collect(Collectors.toList())
            );
        }
        /*封装处理结果*/
        HashMap<String, Object> resultMap = new HashMap<>();
        resultMap.put("content", contents);
        resultMap.put("image", images);
        return resultMap;
    }


    /**
     * 自管理敏感词审核
     * @param content
     * @param wmNews
     * @return
     */
    private boolean handleSensitive(String content, WmNews wmNews) {

        boolean flag = true;
        // 查询所有敏感词
        List<String> sensitiveList = adSensitiveMapper.findAllSensitive();
        // 初始化 DFA搜索
        SensitiveWordUtil.initMap(sensitiveList);
        // 匹配敏感词
        Map<String, Integer> map = SensitiveWordUtil.matchWords(content);

        if (map.size() > 0) {
            flag = false;
            updateWmNews(wmNews,(short) 2,"文章中包含敏感词"+map);
        }

        return flag;
    }
    /**
     * 修改文章
     * @param wmNews
     * @param status
     * @param msg
     */
    private void updateWmNews(WmNews wmNews, short status, String msg) {
        wmNews.setStatus(status);
        wmNews.setReason(msg);
        ResponseResult responseResult = wemediaFeign.updateWmNews(wmNews);
        if(!responseResult.getCode().equals(0)){
            CustException.cust(AppHttpCodeEnum.WEMEDIA_UPDATE_ERROR);
        }
    }

    private void saveAppArticle(WmNews wmNews) {
        /*保存app相关文章*/
        ResponseResult responseResult = saveArtical(wmNews);
        if (!responseResult.getCode().equals(0)) {
            throw new RuntimeException("文章审核保存app文章失败");
        }
        Object data = responseResult.getData();
        //修改自媒体文章状态，状态为9  审核通过
        wmNews.setArticleId((long) data);
        updateWmNews(wmNews, (short) 9, "文章审核通过");

    }

    /**
     * 执行保存文章（三张表）
     * @param wmNews
     * @return
     */
    private ResponseResult saveArtical(WmNews wmNews) {
        ArticleDto articleDto = new ArticleDto();
        BeanUtils.copyProperties(wmNews, articleDto);
        if (wmNews.getArticleId() != null) {
            articleDto.setId(wmNews.getArticleId());
        }
        /*布局*/
        articleDto.setLayout(wmNews.getType());
        articleDto.setFlag((byte) 0);
        /*设置频道*/
        if (wmNews.getChannelId() != null) {
            articleDto.setChannelId(wmNews.getChannelId());
            AdChannel adChannel = adChannelMapper.selectById(wmNews.getChannelId());

            if (adChannel != null) {
                articleDto.setChannelName(adChannel.getName());
            }
        }
        /*3设置作者信息*/
        // 查wm_user 状态
        WmUser wmUser = wemediaFeign.findWmUserById(wmNews.getUserId());
        if (wmUser == null || wmUser.getStatus().intValue() != 9) { // 非法用户
            CustException.cust(AppHttpCodeEnum.ADMIN_ADUSER_ISNOTEXIT_ERROR);
        }
        if (StringUtils.isNotBlank(wmUser.getName())) {
            // 自媒体名称不能修改
            articleDto.setAuthorName(wmUser.getName());
            // 作者id 尽量减少远程调用
        }

        //4 文章内容
        articleDto.setContent(wmNews.getContent());

        // 发起远程调用 保存 三张表数据, 返回值必须携带文章id
        return articleFeign.saveArticle(articleDto);
    }
}
